package repository

import (
	"database/sql"
	"sen-golang-study/go_game_study/hero_story_go_server/common/log"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/domain/user/entity"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/domain/user/valueobject"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/infrastructure/database"
)

// UserRepositoryImpl 用户仓储实现
type UserRepositoryImpl struct {
	db *sql.DB
}

// NewUserRepository 创建用户仓储实现
func NewUserRepository() UserRepository {
	return &UserRepositoryImpl{
		db: database.GetDB(),
	}
}

const (
	sqlGetUserByName = `SELECT user_id, user_name, password, hero_avatar, cur_hp, create_time, last_login_time FROM t_user WHERE user_name = ?`
	sqlGetUserByID   = `SELECT user_id, user_name, password, hero_avatar, cur_hp, create_time, last_login_time FROM t_user WHERE user_id = ?`
	sqlInsertUser    = `INSERT INTO t_user (user_name, password, hero_avatar, cur_hp, create_time, last_login_time) VALUES (?, ?, ?, ?, ?, ?)`
	sqlUpdateUser    = `UPDATE t_user SET password = ?, hero_avatar = ?, cur_hp = ?, last_login_time = ? WHERE user_id = ?`
	sqlDeleteUser    = `DELETE FROM t_user WHERE user_id = ?`
	sqlExistsUser    = `SELECT COUNT(1) FROM t_user WHERE user_name = ?`
	sqlSaveOrUpdate  = `INSERT INTO t_user (user_name, password, hero_avatar, cur_hp, create_time, last_login_time) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE cur_hp = VALUES(cur_hp), last_login_time = VALUES(last_login_time)`
)

// GetByUserName 根据用户名获取用户
func (r *UserRepositoryImpl) GetByUserName(userName string) (*entity.User, error) {
	if len(userName) <= 0 {
		return nil, nil
	}

	row := r.db.QueryRow(sqlGetUserByName, userName)
	if row == nil {
		return nil, nil
	}

	var userID uint32
	var name, password, heroAvatar string
	var curHP uint32
	var createTime, lastLoginTime int64

	err := row.Scan(&userID, &name, &password, &heroAvatar, &curHP, &createTime, &lastLoginTime)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		log.Error("查询用户失败: %+v", err)
		return nil, err
	}

	user := entity.NewUser(name, password, heroAvatar, createTime)
	user.SetUserID(userID)
	user.SetCurHP(curHP)
	user.UpdateLastLoginTime(lastLoginTime)
	user.SetMoveState(valueobject.NewMoveState())

	return user, nil
}

// GetByUserID 根据用户ID获取用户
func (r *UserRepositoryImpl) GetByUserID(userID uint32) (*entity.User, error) {
	if userID <= 0 {
		return nil, nil
	}

	row := r.db.QueryRow(sqlGetUserByID, userID)
	if row == nil {
		return nil, nil
	}

	var id uint32
	var name, password, heroAvatar string
	var curHP uint32
	var createTime, lastLoginTime int64

	err := row.Scan(&id, &name, &password, &heroAvatar, &curHP, &createTime, &lastLoginTime)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		log.Error("查询用户失败: %+v", err)
		return nil, err
	}

	user := entity.NewUser(name, password, heroAvatar, createTime)
	user.SetUserID(id)
	user.SetCurHP(curHP)
	user.UpdateLastLoginTime(lastLoginTime)
	user.SetMoveState(valueobject.NewMoveState())

	return user, nil
}

// Save 保存用户
func (r *UserRepositoryImpl) Save(user *entity.User) error {
	if user == nil {
		return nil
	}

	result, err := r.db.Exec(sqlInsertUser,
		user.GetUserName(),
		user.GetPassword(),
		user.GetHeroAvatar(),
		user.GetCurHP(),
		user.GetCreateTime(),
		user.GetLastLoginTime())

	if err != nil {
		log.Error("保存用户失败: %+v", err)
		return err
	}

	// 获取自增ID
	lastInsertID, err := result.LastInsertId()
	if err != nil {
		log.Error("获取用户ID失败: %+v", err)
		return err
	}

	user.SetUserID(uint32(lastInsertID))
	return nil
}

// Update 更新用户
func (r *UserRepositoryImpl) Update(user *entity.User) error {
	if user == nil {
		return nil
	}

	_, err := r.db.Exec(sqlUpdateUser,
		user.GetPassword(),
		user.GetHeroAvatar(),
		user.GetCurHP(),
		user.GetLastLoginTime(),
		user.GetUserID())

	if err != nil {
		log.Error("更新用户失败: %+v", err)
		return err
	}

	return nil
}

// SaveOrUpdate 保存或更新用户
func (r *UserRepositoryImpl) SaveOrUpdate(user *entity.User) error {
	if user == nil {
		return nil
	}

	result, err := r.db.Exec(sqlSaveOrUpdate,
		user.GetUserName(),
		user.GetPassword(),
		user.GetHeroAvatar(),
		user.GetCurHP(),
		user.GetCreateTime(),
		user.GetLastLoginTime())

	if err != nil {
		log.Error("保存或更新用户失败: %+v", err)
		return err
	}

	// 如果用户ID为0，说明是新插入的记录，需要设置ID
	if user.GetUserID() == 0 {
		lastInsertID, err := result.LastInsertId()
		if err != nil {
			log.Error("获取用户ID失败: %+v", err)
			return err
		}
		user.SetUserID(uint32(lastInsertID))
	}

	return nil
}

// Delete 删除用户
func (r *UserRepositoryImpl) Delete(userID uint32) error {
	if userID <= 0 {
		return nil
	}

	_, err := r.db.Exec(sqlDeleteUser, userID)
	if err != nil {
		log.Error("删除用户失败: %+v", err)
		return err
	}

	return nil
}

// Exists 检查用户是否存在
func (r *UserRepositoryImpl) Exists(userName string) (bool, error) {
	if len(userName) <= 0 {
		return false, nil
	}

	var count int
	err := r.db.QueryRow(sqlExistsUser, userName).Scan(&count)
	if err != nil {
		log.Error("检查用户是否存在失败: %+v", err)
		return false, err
	}

	return count > 0, nil
}